package com.xnyzc.lhy.mis.service.impl.cms.vehicle;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xnyzc.lhy.common.component.convert.DateToStringConverter;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.cms.veh.EIsUse;
import com.xnyzc.lhy.common.penum.cms.veh.EVehFuelType;
import com.xnyzc.lhy.common.penum.vehicle.EVehicleStatus;
import com.xnyzc.lhy.common.penum.vehicle.EvehicleType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.mis.entity.result.cms.driver.CmsDriverRes;
import com.xnyzc.lhy.mis.entity.result.cms.veh.CanAssignVehicle;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.mis.entity.user.OaDUser;
import com.xnyzc.lhy.mis.entity.vehicle.OaDDriverVehicle;
import com.xnyzc.lhy.mis.entity.vehicle.OaSysVehicle;
import com.xnyzc.lhy.mis.mapper.cms.veh.CanAssignVehicleMapper;
import com.xnyzc.lhy.mis.mapper.user.OaDUserMapper;
import com.xnyzc.lhy.mis.mapper.vehicle.OaDDriverVehicleMapper;
import com.xnyzc.lhy.mis.mapper.vehicle.OaSysVehicleMapper;
import com.xnyzc.lhy.mis.service.cms.util.IOaSysGetOfficeIdListService;
import com.xnyzc.lhy.mis.service.cms.vehicle.ICanAssignVehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * @Description 分配车辆
 * @Author zhuyubin
 * @Date 2019-08-26 11:40
 **/
@Service
public class CanAssignVehicleServiceImpl implements ICanAssignVehicleService {

    @Autowired
    private IOaSysGetOfficeIdListService iOaSysGetOfficeIdListService;
    @Autowired
    private CanAssignVehicleMapper canAssignVehicleMapper;
    @Autowired
    private OaDDriverVehicleMapper oaDDriverVehicleMapper;
    @Autowired
    private OaDUserMapper oaDUserMapper;
    @Autowired
    private OaSysVehicleMapper oaSysVehicleMapper;
    @Autowired
    private RedisCommon redisCommon;

    /**
     * 获取司机信息并关联车辆
     * @param sysUserId 后台用户id
     * @param type 数据等级
     * @param tag 租户
     * @param current 当前页
     * @return
     */
    @Override
    public IPage<CmsDriverRes> selectDriverPage(Long sysUserId, List<String> type, String tag, Long current, String name, String phone, String vehNo){
        List<Long> driverIds = iOaSysGetOfficeIdListService.selectDUserIdList(sysUserId, type);
        IPage<OaDUser> oaDUserIPage = new Page<>();
        oaDUserIPage.setCurrent(current);
        // 司机信息
        LambdaQueryWrapper<OaDUser> oaDUserQW = Wrappers.<OaDUser>lambdaQuery()
                .eq(OaDUser::getTag, tag)
                .in(OaDUser::getDriverId, driverIds);
        if (CheckUtil.objIsNotEmpty(name)){
            oaDUserQW.like(OaDUser::getDriverName, name);
        }
        if (CheckUtil.objIsNotEmpty(phone)){
            oaDUserQW.like(OaDUser::getDriverPhone, phone);
        }
        if (CheckUtil.objIsNotEmpty(vehNo)){
            List<OaSysVehicle> oaSysVehicles = oaSysVehicleMapper.selectList(
                    Wrappers.<OaSysVehicle>lambdaQuery()
                            .eq(OaSysVehicle::getTag, tag)
                            .like(OaSysVehicle::getVehNo, vehNo));
            List<Long> vehicleIds = new ArrayList<>();
            for (OaSysVehicle oaSysVehicle : oaSysVehicles) {
                Long vehicleId = oaSysVehicle.getVehicleId();
                if (CheckUtil.objIsNotEmpty(vehicleId)){
                    vehicleIds.add(vehicleId);
                }
            }
            List<OaDDriverVehicle> oaDDriverVehicles = oaDDriverVehicleMapper.selectList(
                    Wrappers.<OaDDriverVehicle>lambdaQuery()
                            .eq(OaDDriverVehicle::getTag, tag)
                            .in(OaDDriverVehicle::getVehicleId, vehicleIds));
            List<Long> driverIdList = new ArrayList<>();
            for (OaDDriverVehicle oaDDriverVehicle : oaDDriverVehicles) {
                if (CheckUtil.objIsNotEmpty(oaDDriverVehicle.getDriverId())){
                    driverIdList.add(oaDDriverVehicle.getDriverId());
                }
            }
            driverIds.retainAll(driverIdList);
        }
        IPage<OaDUser> userIPage = oaDUserMapper.selectPage(oaDUserIPage, oaDUserQW);
        // 司机车辆关联
        List<OaDDriverVehicle> oaDDriverVehicles = oaDDriverVehicleMapper.selectList(
                Wrappers.<OaDDriverVehicle>lambdaQuery()
                    .eq(OaDDriverVehicle::getTag, tag)
                    .in(OaDDriverVehicle::getDriverId, driverIds)
                    .orderByDesc(OaDDriverVehicle::getCreateTime));
        List<CmsDriverRes> cmsDriverResList = this.getCmsDriverResList(userIPage, oaDDriverVehicles);
        List<Long> vehicleIds = new ArrayList<>();
        for (CmsDriverRes cmsDriverRes : cmsDriverResList) {
            vehicleIds.add(cmsDriverRes.getVehicleId());
        }
        // 车辆信息
        List<OaSysVehicle> oaSysVehicles = oaSysVehicleMapper.selectList(
                Wrappers.<OaSysVehicle>lambdaQuery()
                    .eq(OaSysVehicle::getTag, tag)
                    .in(OaSysVehicle::getVehicleId, vehicleIds));
        for (CmsDriverRes cmsDriverRes : cmsDriverResList) {
            for (OaSysVehicle oaSysVehicle : oaSysVehicles) {
                if (oaSysVehicle.getVehicleId().equals(cmsDriverRes.getVehicleId())){
                    cmsDriverRes.setVehNo(oaSysVehicle.getVehNo());
                    cmsDriverRes.setVehType(CheckUtil.objIsEmpty(oaSysVehicle.getVehType()) ? "" : EvehicleType.findById(oaSysVehicle.getVehType()).getValue());
                }
            }
        }
        IPage<CmsDriverRes> page = new Page<>();
        page.setPages(userIPage.getPages());
        page.setRecords(cmsDriverResList);
        page.setTotal(userIPage.getTotal());
        page.setSize(userIPage.getSize());
        page.setCurrent(userIPage.getCurrent());
        return page;
    }

    /**
     * 可分配车辆列表
     * @param sysUserId 后台用户
     * @param tag 租户
     * @param current 当前页
     * @return
     */
    @Override
    public IPage selectOaSysVehiclePage(Long sysUserId, String tag, Long current, String vehNo, Long officeId){
        IPage<Map<String, Object>> page = new Page<>();
        QueryWrapper<CanAssignVehicle> queryWrapper = iOaSysGetOfficeIdListService.dataScopeFilter(sysUserId, "oso", "osu");
        queryWrapper.and(wrapper -> wrapper.eq(String.format("oddv.%s", OaDDriverVehicle.IS_USE), 0).or().isNull(String.format("oddv.%s", OaDDriverVehicle.IS_USE)));
        queryWrapper
                .eq(String.format("osv.%s", OaSysVehicle.TAG), tag)
                .eq(String.format("oso.%s", OaSysOffice.OFFICE_ID), officeId)
                .groupBy(String.format("osv.%s", OaSysVehicle.VEHICLE_ID));
        queryWrapper.orderByDesc(String.format("osv.%s", OaSysVehicle.CREATE_TIME));
        if (CheckUtil.objIsNotEmpty(vehNo)){
            queryWrapper.like(String.format("osv.%s", OaSysVehicle.VEH_NO), vehNo);
        }
        Page<CanAssignVehicle> canAssignVehiclePage = new Page<>();
        canAssignVehiclePage.setCurrent(current);
        IPage<CanAssignVehicle> canAssignVehicleIPage = canAssignVehicleMapper.selectCanAssignVehiclePage(canAssignVehiclePage, queryWrapper);
        List<Map<String, Object>> list = new ArrayList<>();
        for (CanAssignVehicle canAssignVehicle : canAssignVehicleIPage.getRecords()) {
            Map<String, Object> map = new HashMap<>(16);
            map.put("vehicleId", canAssignVehicle.getVehicleId());
            map.put("vehNo", canAssignVehicle.getVehNo());
            map.put("name", canAssignVehicle.getName());
            map.put("vehStatus", CheckUtil.objIsEmpty(canAssignVehicle.getVehStatus()) ? "" : EVehicleStatus.findById(Integer.valueOf(canAssignVehicle.getVehStatus())).getValue());
            map.put("vehColor", CheckUtil.objIsEmpty(canAssignVehicle.getVehColor()) ? "" : canAssignVehicle.getVehColor());
            map.put("vehSeatsNumber", this.isNull(canAssignVehicle.getVehSeatsNumber()));
            map.put("vehEngineNumber", this.isNull(canAssignVehicle.getVehEngineNumber()));
            map.put("vehFrameNumber", this.isNull(canAssignVehicle.getVehFrameNumber()));
            map.put("vehFuelType", CheckUtil.objIsEmpty(canAssignVehicle.getVehFuelType()) ? "" : EVehFuelType.findById(canAssignVehicle.getVehFuelType()).getDesc());
            map.put("vehType", CheckUtil.objIsEmpty(canAssignVehicle.getVehType()) ? "" : EvehicleType.findById(canAssignVehicle.getVehType()).getValue());
            list.add(map);
        }
        page.setPages(canAssignVehicleIPage.getPages());
        page.setRecords(list);
        page.setTotal(canAssignVehicleIPage.getTotal());
        page.setSize(canAssignVehicleIPage.getSize());
        page.setCurrent(canAssignVehicleIPage.getCurrent());
        return page;
    }

    /**
     * 分配车辆
     * @param sysUserId 当前管理员id
     * @param driverId 司机id
     * @param vehicleId 车辆id
     * @param tag 租户
     * @return
     */
    @Override
    public String assignVehicle(Long sysUserId, Long driverId, Long vehicleId, String tag){
        Date date = new Date();
        OaDDriverVehicle driverVehicle = oaDDriverVehicleMapper.selectOne(
                Wrappers.<OaDDriverVehicle>lambdaQuery()
                        .eq(OaDDriverVehicle::getTag, tag)
                        .eq(OaDDriverVehicle::getDriverId, driverId)
                        .eq(OaDDriverVehicle::getIsUse, EIsUse.yes.getValue()));
        // 是否有使用车辆
        if (CheckUtil.objIsNotEmpty(driverVehicle)){
            throw PangException.create(EErrorCode.assignVehicleRepeat);
        }
        OaDDriverVehicle oaDDriverVehicle = oaDDriverVehicleMapper.selectOne(
                Wrappers.<OaDDriverVehicle>lambdaQuery()
                        .eq(OaDDriverVehicle::getTag, tag)
                        .eq(OaDDriverVehicle::getDriverId, driverId));
        // 没有关联数据新建一条
        if (CheckUtil.objIsEmpty(oaDDriverVehicle)){
            OaDDriverVehicle dDriverVehicle = new OaDDriverVehicle();
            dDriverVehicle.setLinkedId(IDUtil.nextId());
            dDriverVehicle.setDriverId(driverId);
            dDriverVehicle.setVehicleId(vehicleId);
            dDriverVehicle.setIsUse(EIsUse.yes.getValue());
            dDriverVehicle.setTag(tag);
            dDriverVehicle.setCreateUser(sysUserId);
            dDriverVehicle.setCreateTime(date);
            dDriverVehicle.setUpdateUser(sysUserId);
            dDriverVehicle.setUpdateTime(date);
            int i = oaDDriverVehicleMapper.insert(dDriverVehicle);
            if (i != 1){
                throw PangException.create(EErrorCode.assignVehicleFailure);
            }
        }
        // 有数据则更新
        else {
            oaDDriverVehicle.setIsUse(EIsUse.yes.getValue());
            oaDDriverVehicle.setUpdateTime(date);
            oaDDriverVehicle.setVehicleId(vehicleId);
            oaDDriverVehicle.setUpdateUser(sysUserId);
            int i = oaDDriverVehicleMapper.updateById(oaDDriverVehicle);
            if (i != 1){
                throw PangException.create(EErrorCode.assignVehicleFailure);
            }
        }
        return EErrorCode.assignVehicleSuccess.getDesc();
    }

    /**
     * 取消分配车辆
     * @param sysUserId 后台用户
     * @param tag 租户
     * @param driverId 司机id
     * @param vehicleId 车辆id
     * @return
     */
    @Override
    public String cancelAssignVehicle(Long sysUserId, String tag, Long driverId, Long vehicleId){
        // 接单中不允许取消分配
        String jsonStr = redisCommon.getStr(String.format("%s%s", RedisPrefixConstant.GPS_VEH_KEY_PREFIX, driverId));
        if (CheckUtil.objIsNotEmpty(jsonStr)){
            throw PangException.create(EErrorCode.receivingOrder);
        }
        // 上班中不允许取消分配
        String redisKey = String.format("%s%s", RedisPrefixConstant.WORK_OA_D_WORK_STATISTICS, driverId);
        jsonStr = redisCommon.getStr(redisKey);
        if (CheckUtil.objIsNotEmpty(jsonStr)){
            throw PangException.create(EErrorCode.atWork);
        }
        OaDDriverVehicle oaDDriverVehicle = oaDDriverVehicleMapper.selectOne(
                Wrappers.<OaDDriverVehicle>lambdaQuery()
                        .eq(OaDDriverVehicle::getTag, tag)
                        .eq(OaDDriverVehicle::getDriverId, driverId)
                        .eq(OaDDriverVehicle::getVehicleId, vehicleId));
        if (CheckUtil.objIsEmpty(oaDDriverVehicle)){
            throw PangException.create(EErrorCode.unCancelAssignVehicle);
        }
        if (EIsUse.no.getValue().equals(oaDDriverVehicle.getIsUse())){
            throw PangException.create(EErrorCode.unCancelAssignVehicle);
        }
        oaDDriverVehicle.setVehicleId(-1L);
        oaDDriverVehicle.setIsUse(EIsUse.no.getValue());
        oaDDriverVehicle.setUpdateTime(new Date());
        oaDDriverVehicle.setUpdateUser(sysUserId);
        int i = oaDDriverVehicleMapper.updateById(oaDDriverVehicle);
        if (i != 1){
            throw PangException.create(EErrorCode.cancelAssignVehicleFailure);
        }
        return EErrorCode.cancelAssignVehicleSuccess.getDesc();
    }

    /**
     * 封装出参
     * @param userIPage
     * @param oaDDriverVehicles
     * @return
     */
    private List<CmsDriverRes> getCmsDriverResList(IPage<OaDUser> userIPage, List<OaDDriverVehicle> oaDDriverVehicles){
        List<CmsDriverRes> cmsDriverResList = new ArrayList<>();
        // 正在使用
        Integer yseIsUse = EIsUse.yes.getValue();
        for (OaDUser oaDUser : userIPage.getRecords()) {
            Long driverId = oaDUser.getDriverId();
            CmsDriverRes cmsDriverRes = new CmsDriverRes();
            cmsDriverRes.setDriverId(driverId);
            cmsDriverRes.setDriverName(oaDUser.getDriverName());
            cmsDriverRes.setDriverPhone(oaDUser.getDriverPhone());
            for (OaDDriverVehicle oaDDriverVehicle : oaDDriverVehicles) {
                if (driverId.equals(oaDDriverVehicle.getDriverId())){
                    if (yseIsUse.equals(oaDDriverVehicle.getIsUse())){
                        cmsDriverRes.setVehicleId(oaDDriverVehicle.getVehicleId());
                        cmsDriverRes.setUpdateTime(new DateToStringConverter().convert(oaDDriverVehicle.getUpdateTime()));
                    }
                }
            }
            cmsDriverResList.add(cmsDriverRes);
        }
        return cmsDriverResList;
    }

    /**
     * 空处理
     * @param value
     * @return
     */
    private String isNull(Object value){
        return CheckUtil.objIsEmpty(value) ? "" : value.toString();
    }
}
